#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 20, M = 1 << N;
const int INF = 0x3f;
int g[N][N];
int f[M][N];
int n;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n;
    memset(f, INF, sizeof f);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            cin >> g[i][j];
    f[1][0] = 0;
    // 起点固定是1, 所以在遍历状态的时候最低位一定是1
    // 可以将起点从1开始，步长为2
    for (int i = 1; i < 1 << n; i += 2)
        for (int j = 1; j < n; ++j)
            // 只有i经过第j个点才是有效的
            if (i >> j & 1)
                // 遍历所有倒数第二个点的可能性，求最小值
                for (int k = 0; k < n; ++k)
                    if (k != j && (i >> k & 1))
                        f[i][j] = min(f[i][j], f[i - (1 << j)][k] + g[k][j]);
    cout << f[(1 << n) - 1][n - 1] << endl;
    return 0;
}
